From: sos22@douglas.cl.cam.ac.uk Date: Thu, 26 Jan 2006 18:40:13 +0000 (+0100) Subject: Create a block of reserved PFNs in shadow translate mode guests, and X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16525 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=5f97716503fb958c57201fee7ae7b4a578510812;p=xen.git Create a block of reserved PFNs in shadow translate mode guests, and move the shared info and grant table pfns into that block. This allows us to remove the get_gnttablist dom0 op, and simplifies the domain creation code slightly. Having the reserved block managed by Xen may also make it slightly easier to handle the case where the grant table needs to be extended at run time. Suggested-by: kaf24 Signed-off-by: Steven Smith, sos22@cam.ac.uk --- diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 3c80b5e994..30e7abd5ac 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -610,7 +610,7 @@ static int setup_guest(int xc_handle, goto error_out; } - if ( (page_array = malloc((nr_pages + 1 + NR_GRANT_FRAMES) * sizeof(unsigned long))) == NULL ) + if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) { PERROR("Could not allocate memory"); goto error_out; @@ -651,17 +651,7 @@ static int setup_guest(int xc_handle, xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[physmap_pfn++]); - page_array[nr_pages] = shared_info_frame; - - if ( xc_get_gnttab_frames(xc_handle, - dom, - page_array + 1 + nr_pages, - NR_GRANT_FRAMES) <= 0) { - fprintf(stderr, "cannot get grant table frames\n"); - goto error_out; - } - - for ( count = 0; count < nr_pages + 1 + NR_GRANT_FRAMES; count++ ) + for ( count = 0; count < nr_pages; count++ ) { if ( xc_add_mmu_update( xc_handle, mmu, @@ -696,6 +686,16 @@ static int setup_guest(int xc_handle, PERROR("Could not enable translation mode"); goto error_out; } + + /* Find the shared info frame. It's guaranteed to be at the + start of the PFN hole. */ + guest_shared_info_mfn = xc_get_pfn_hole_start(xc_handle, dom); + if (guest_shared_info_mfn <= 0) { + PERROR("Cannot find shared info pfn"); + goto error_out; + } + } else { + guest_shared_info_mfn = shared_info_frame; } /* setup page tables */ @@ -756,11 +756,9 @@ static int setup_guest(int xc_handle, if (shadow_mode_enabled) { guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT; guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT; - guest_shared_info_mfn = nr_pages; } else { guest_store_mfn = *store_mfn; guest_console_mfn = *console_mfn; - guest_shared_info_mfn = shared_info_frame; } start_info = xc_map_foreign_range( diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 13848fbf5f..1f5ae861a5 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -131,6 +131,14 @@ int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low, return rc; } +int xc_get_pfn_hole_start(int xc_handle, domid_t dom) +{ + struct mmuext_op op = {0}; + op.cmd = MMUEXT_PFN_HOLE_BASE; + return xc_mmuext_op(xc_handle, &op, 1, dom); +} + + /* * Local variables: * mode: C diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 8993af0b57..75556f6847 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -314,35 +314,6 @@ int xc_get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -int xc_get_gnttab_frames(int xc_handle, - uint32_t domid, - unsigned long *pfn_buf, - unsigned long max_pfns) -{ - DECLARE_DOM0_OP; - int ret; - op.cmd = DOM0_GETGNTTABLIST; - op.u.getgnttablist.domain = (domid_t)domid; - op.u.getgnttablist.max_pfns = max_pfns; - op.u.getgnttablist.buffer = pfn_buf; - -#ifdef VALGRIND - memset(pfn_buf, 0, max_pfns * sizeof(unsigned long)); -#endif - - if ( mlock(pfn_buf, max_pfns * sizeof(unsigned long)) != 0 ) - { - PERROR("xc_get_pfn_list: pfn_buf mlock failed"); - return -1; - } - - ret = do_dom0_op(xc_handle, &op); - - safe_munlock(pfn_buf, max_pfns * sizeof(unsigned long)); - - return (ret < 0) ? -1 : op.u.getgnttablist.num_pfns; -} - long xc_get_tot_pages(int xc_handle, uint32_t domid) { DECLARE_DOM0_OP; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index b366db69e5..8c19ecd218 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -111,9 +111,6 @@ static inline int do_dom0_op(int xc_handle, dom0_op_t *op) return ret; } -int xc_get_gnttab_frames(int xc_handle, uint32_t domid, unsigned long *pfn_buf, - unsigned long max_pfns); - /* * ioctl-based mfn mapping interface diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 91d717c55c..6585d1a6e2 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -528,4 +528,6 @@ int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu, unsigned long long ptr, unsigned long long val); int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu); +int xc_get_pfn_hole_start(int xc_handle, domid_t dom); + #endif diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 4a61ba4948..789d01899a 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -330,38 +330,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) } break; - case DOM0_GETGNTTABLIST: - { - int i; - struct domain *d = find_domain_by_id(op->u.getgnttablist.domain); - unsigned long max_pfns = op->u.getgnttablist.max_pfns; - unsigned long pfn; - unsigned long *buffer = op->u.getgnttablist.buffer; - - ret = -EINVAL; - if ( d != NULL ) - { - ret = 0; - - for ( i = 0; i < max_pfns && i < NR_GRANT_FRAMES; i++ ) - { - pfn = gnttab_shared_mfn(d, d->grant_table, i); - if ( put_user(pfn, buffer) ) - { - ret = -EFAULT; - break; - } - buffer++; - } - - op->u.getgnttablist.num_pfns = i; - copy_to_user(u_dom0_op, op, sizeof(*op)); - - put_domain(d); - } - } - break; - case DOM0_GETMEMLIST: { int i; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 61a26de580..ad89d5fdec 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1929,7 +1929,57 @@ int do_mmuext_op( } break; } - + + case MMUEXT_PFN_HOLE_BASE: + { + if (FOREIGNDOM->start_pfn_hole) { + rc = FOREIGNDOM->start_pfn_hole; + okay = 1; + } else { + rc = FOREIGNDOM->start_pfn_hole = + FOREIGNDOM->max_pages; + okay = 1; + if (shadow_mode_translate(FOREIGNDOM)) { + /* Fill in a few entries in the hole. At the + moment, this means the shared info page and the + grant table pages. */ + struct domain_mmap_cache c1, c2; + unsigned long pfn, mfn, x; + domain_mmap_cache_init(&c1); + domain_mmap_cache_init(&c2); + shadow_lock(FOREIGNDOM); + pfn = FOREIGNDOM->start_pfn_hole; + mfn = virt_to_phys(FOREIGNDOM->shared_info) >> PAGE_SHIFT; + set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2); + set_pfn_from_mfn(mfn, pfn); + pfn++; + for (x = 0; x < NR_GRANT_FRAMES; x++) { + mfn = gnttab_shared_mfn(FOREIGNDOM, + FOREIGNDOM->grant_table, + x); + set_p2m_entry(FOREIGNDOM, pfn, mfn, &c1, &c2); + set_pfn_from_mfn(mfn, pfn); + pfn++; + } + shadow_unlock(FOREIGNDOM); + domain_mmap_cache_destroy(&c1); + domain_mmap_cache_destroy(&c2); + } + } + break; + } + + case MMUEXT_PFN_HOLE_SIZE: + { + if (shadow_mode_translate(FOREIGNDOM)) { + rc = PFN_HOLE_SIZE; + } else { + rc = 0; + } + okay = 1; + break; + } + default: MEM_LOG("Invalid extended pt command 0x%x", op.cmd); okay = 0; @@ -2663,7 +2713,7 @@ long set_gdt(struct vcpu *v, long do_set_gdt(unsigned long *frame_list, unsigned int entries) { - int i, nr_pages = (entries + 511) / 512; + int nr_pages = (entries + 511) / 512; unsigned long frames[16]; long ret; diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index d5d0e0acb0..b6376d3d6b 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -60,6 +60,9 @@ #endif #endif +/* How large is the PFN reserved area, when we have one? */ +#define PFN_HOLE_SIZE 32 + #ifndef STACK_ORDER #define STACK_ORDER 1 #endif diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 6d6a04594e..6e99efcd10 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -431,16 +431,6 @@ typedef struct { unsigned long mfn; /* machine frame to be initialised */ } dom0_hypercall_init_t; -#define DOM0_GETGNTTABLIST 49 -typedef struct { - /* IN variables. */ - domid_t domain; - unsigned long max_pfns; - void *buffer; - /* OUT variables. */ - unsigned long num_pfns; -} dom0_getgnttablist_t; - typedef struct { uint32_t cmd; uint32_t interface_version; /* DOM0_INTERFACE_VERSION */ @@ -482,7 +472,6 @@ typedef struct { dom0_irq_permission_t irq_permission; dom0_iomem_permission_t iomem_permission; dom0_hypercall_init_t hypercall_init; - dom0_getgnttablist_t getgnttablist; uint8_t pad[128]; } u; } dom0_op_t; diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index ca1d4d1d03..0027e327e4 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -144,6 +144,15 @@ * cmd: MMUEXT_SET_LDT * linear_addr: Linear address of LDT base (NB. must be page-aligned). * nr_ents: Number of entries in LDT. + * + * cmd: MMUEXT_PFN_HOLE_BASE + * No additional arguments. Returns the first pfn in the Xen-reserved + * pfn hole. Note that we delay allocating the hole until the first + * time this is called. + * + * cmd: MMUEXT_PFN_HOLE_SIZE + * No additional arguments. Returns the number of pfns in the + * Xen-reserved pfn hole. */ #define MMUEXT_PIN_L1_TABLE 0 #define MMUEXT_PIN_L2_TABLE 1 @@ -160,6 +169,8 @@ #define MMUEXT_FLUSH_CACHE 12 #define MMUEXT_SET_LDT 13 #define MMUEXT_NEW_USER_BASEPTR 15 +#define MMUEXT_PFN_HOLE_BASE 16 +#define MMUEXT_PFN_HOLE_SIZE 17 #ifndef __ASSEMBLY__ struct mmuext_op { diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 0d265badb8..f164a7cc7a 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -153,6 +153,9 @@ struct domain /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; + + /* Start of the PFN hole */ + unsigned long start_pfn_hole; }; struct domain_setup_info